/*
 * kernel/command/cmd-lcdscreen.c
 */

#include <cairo-xboot.h>
#include <cairo-ft.h>
#include <shell/ctrlc.h>
#include <input/input.h>
#include <input/keyboard.h>
#include <command/command.h>
#include <rk3288-gpio.h>
#include <gpio/gpio.h>

static void usage(void)
{
	printf("usage:\r\n");
	printf("    lcdscreen [args ...]\r\n");
}

struct display_t {
	struct fb_t * fb;
	cairo_surface_t * alone;
	cairo_surface_t * cs[2];
	cairo_t * cr[2];
	int index;
};

static struct display_t * display_alloc(const char * name)
{
	struct display_t * display;
	struct fb_t * fb;

	if(!(fb = name ? search_fb(name) : search_first_fb()))
		return NULL;

	display = malloc(sizeof(struct display_t));
	if(!display)
		return NULL;

	display->fb = fb;
	display->alone = cairo_xboot_surface_create(display->fb, display->fb->alone);
	display->cs[0] = cairo_xboot_surface_create(display->fb, NULL);
	display->cs[1] = cairo_xboot_surface_create(display->fb, NULL);
	display->cr[0] = cairo_create(display->cs[0]);
	display->cr[1] = cairo_create(display->cs[1]);
	display->index = 0;

	return display;
}

static void display_free(struct display_t * display)
{
	if(display)
	{
		cairo_xboot_surface_present(display->alone);
		cairo_surface_destroy(display->alone);
		cairo_destroy(display->cr[0]);
		cairo_destroy(display->cr[1]);
		cairo_surface_destroy(display->cs[0]);
		cairo_surface_destroy(display->cs[1]);
	}
}

static int display_width(struct display_t * display)
{
	if(display)
		return cairo_image_surface_get_width(display->alone);
	return 0;
}

static int display_height(struct display_t * display)
{
	if(display)
		return cairo_image_surface_get_height(display->alone);
	return 0;
}

static cairo_t * display_present(struct display_t * display)
{
	cairo_xboot_surface_present(display->cs[display->index]);
	display->index = (display->index + 1) % 2;
	return display->cr[display->index];
}

static cairo_font_face_t * cairo_font_face_alloc(const char * font)
{
	cairo_font_face_t * cface;
	FT_Library library;
	FT_Face face;

	FT_Init_FreeType(&library);
	FT_New_Face(library, font, 0, &face);
	cface = cairo_ft_font_face_create_for_ft_face(face, 0);
	return cface;
}

static void cairo_show_title(cairo_t * cr, double width, double height, cairo_font_face_t * face, const char * title)
{
	cairo_text_extents_t extents;

	cairo_save(cr);
	cairo_set_line_width(cr, 3);
	cairo_rectangle(cr, 0, 0, width - 1, height - 1);
	cairo_set_source_rgb(cr, 0.5, 0.5, 0.5);
	cairo_fill_preserve(cr);
	cairo_set_source_rgb(cr, 1, 1, 1);
	cairo_stroke(cr);
	cairo_set_font_face(cr, face);
	cairo_set_font_size(cr, 24);
	cairo_set_source_rgb(cr, 1, 1, 1);
	cairo_text_extents(cr, title, &extents);
	cairo_move_to(cr, (width - extents.width) / 2, (height - extents.height) / 2 + 20);
	cairo_show_text(cr, title);
	cairo_restore(cr);
}

static int do_lcdscreen(int argc, char ** argv)
{
	struct event_t e;
	struct display_t * display = display_alloc(NULL);
	cairo_font_face_t * face = cairo_font_face_alloc("/romdisk/fonts/DroidSansFallback.ttf");
	cairo_t * cr = display_present(display);
	int width = display_width(display);
	int height = display_height(display) - 32;
	int index = 0;

		gpio_set_cfg(RK3288_GPIO8_A2, 0x0);
		gpio_set_rate(RK3288_GPIO8_A2, GPIO_RATE_FAST);
		gpio_set_drv(RK3288_GPIO8_A2, GPIO_DRV_STRONG);
		gpio_set_direction(RK3288_GPIO8_A2,GPIO_DIRECTION_OUTPUT);			//////add

		gpio_set_cfg(RK3288_GPIO8_A1, 0x0);
		gpio_set_rate(RK3288_GPIO8_A1, GPIO_RATE_FAST);
		gpio_set_drv(RK3288_GPIO8_A1, GPIO_DRV_STRONG);
		gpio_set_direction(RK3288_GPIO8_A1,GPIO_DIRECTION_OUTPUT);			//////add

	while(1)
	{

		gpio_set_value(RK3288_GPIO8_A2,0x00);//mdelay(1500);
		gpio_set_value(RK3288_GPIO8_A1,0x00);mdelay(1500);

		if(pump_event(runtime_get()->__event_base, &e))
		{
			if(e.type == EVENT_TYPE_KEY_UP)
			{
				if(e.e.key_up.key == KEY_ESC)
					break;
				else if(e.e.key_up.key == KEY_POWER)
					index = (index + 1) % 6;
			}
			else if(e.type == EVENT_TYPE_TOUCH_END)
			{
				index = (index + 1) % 6;
			}
		}
		if(ctrlc())
			break;

		cairo_save(cr);
		cairo_set_source_rgb(cr, 0.9, 0.9, 0.9);
		cairo_paint(cr);
		cairo_restore(cr);

		gpio_set_value(RK3288_GPIO8_A1,1);//mdelay(1500);		////////add
		gpio_set_value(RK3288_GPIO8_A2,1);mdelay(1500);

		cairo_save(cr);
		switch(index)
		{
		case 0:
			cairo_set_source_rgb(cr, 1, 0, 0);
			cairo_paint(cr);
			printf("    lcd  red [args ...]\r\n");		mdelay(2000);
			break;
		case 1:
			cairo_set_source_rgb(cr, 0, 1, 0);
			cairo_paint(cr);
			printf("    lcd green [args ...]\r\n");		mdelay(2000);
			break;
		case 2:
			cairo_set_source_rgb(cr, 0, 0, 1);
			cairo_paint(cr);
			printf("    lcds   blue [args ...]\r\n");		mdelay(2000);
			break;
		case 3:
			cairo_set_line_width(cr, 0);
			cairo_rectangle(cr, 0, 32 + (height / 3) * 0, width, height / 3);
			cairo_set_source_rgb(cr, 1, 0, 0);
			cairo_fill(cr);
			cairo_rectangle(cr, 0, 32 + (height / 3) * 1, width, height / 3);
			cairo_set_source_rgb(cr, 0, 1, 0);
			cairo_fill(cr);
			cairo_rectangle(cr, 0, 32 + (height / 3) * 2, width, height / 3 + 1);
			cairo_set_source_rgb(cr, 0, 0, 1);
			cairo_fill(cr);
			printf("    lcds    colorbar [args ...]\r\n");		mdelay(2000);
			break;
		case 4:
			cairo_set_source_rgb(cr, 1, 1, 1);
			cairo_paint(cr);
			printf("    lcds  white [args ...]\r\n");		mdelay(2000);
			break;
		case 5:
			cairo_set_source_rgb(cr, 0, 0, 0);
			cairo_paint(cr);
			printf("    lcd   black [args ...]\r\n");		mdelay(2000);
			break;
		default:
			break;
		}
		cairo_restore(cr);

		printf("    lcdscreen [args ...]\r\n");		mdelay(2000);
//		printf("    lcdscreen \'%d\' [args ...]\r\n",cr->status);


		cairo_show_title(cr, width, 32, face, "液晶屏测试");
		cr = display_present(display);
		mdelay(20);
	}

	display_free(display);
	return 0;
}

static struct command_t cmd_lcdscreen = {
	.name	= "lcdscreen",
	.desc	= "lcd screen test",
	.usage	= usage,
	.exec	= do_lcdscreen,
};

static __init void lcdscreen_cmd_init(void)
{
	register_command(&cmd_lcdscreen);
}

static __exit void lcdscreen_cmd_exit(void)
{
	unregister_command(&cmd_lcdscreen);
}

command_initcall(lcdscreen_cmd_init);
command_exitcall(lcdscreen_cmd_exit);
